package archive

import (
	"context"
	"fmt"
	"log"
	"strconv"
	"strings"
	"time"

	"gitlab.com/gitlab-org/gitaly/v14/internal/git"
	"gitlab.com/gitlab-org/gitaly/v14/internal/git/localrepo"
	"gitlab.com/gitlab-org/gitaly/v14/internal/git/repository"
	"gitlab.com/gitlab-org/gitaly/v14/internal/gitaly/archive"
	"gitlab.com/gitlab-org/gitaly/v14/internal/gitaly/config"
	"gitlab.com/gitlab-org/gitaly/v14/internal/storage"
	"path/filepath"
	"io/ioutil"
	"os"
)

const (
	// KeepAroundRetentionDays is the default retention period for keep-around refs
	KeepAroundRetentionDays = 30

	// MergeRequestRetentionDays is the default retention period for merge request refs
	MergeRequestRetentionDays = 90
)

// HousekeepingConfig contains configuration for housekeeping archive checks
type HousekeepingConfig struct {
	Enabled                   bool
	KeepAroundRetentionDays   int
	MergeRequestRetentionDays int
	APIEndpoint               string // API接口地址，用于查询MR状态
	APIToken                  string // API访问token
}

// HousekeepingIntegration provides archive functionality for housekeeping tasks
type HousekeepingIntegration struct {
	cfg            config.Cfg
	locator        storage.Locator
	gitCmdFactory  git.CommandFactory
	storageManager *archive.StorageManager
	gitOperations  *archive.GitOperations
	kafkaProducer  *KafkaProducer
	config         HousekeepingConfig
	lockManager    *archive.LockManager // Added lockManager
}

// NewHousekeepingIntegration creates a new housekeeping integration
func NewHousekeepingIntegration(
	cfg config.Cfg,
	locator storage.Locator,
	gitCmdFactory git.CommandFactory,
	storageManager *archive.StorageManager,
	gitOperations *archive.GitOperations,
	kafkaProducer *KafkaProducer,
	housekeepingConfig HousekeepingConfig,
	lockManager *archive.LockManager, // Added lockManager
) *HousekeepingIntegration {
	return &HousekeepingIntegration{
		cfg:            cfg,
		locator:        locator,
		gitCmdFactory:  gitCmdFactory,
		storageManager: storageManager,
		gitOperations:  gitOperations,
		kafkaProducer:  kafkaProducer,
		config:         housekeepingConfig,
		lockManager:    lockManager,
	}
}

// CheckExpiredRefs checks for expired refs before repack operation
// 统一处理keep-around和merge-requests引用，首先写入新引用到waiting目录，然后处理超期引用
func (hi *HousekeepingIntegration) CheckExpiredRefs(ctx context.Context, repo repository.GitRepo) error {
	if !hi.config.Enabled {
		return nil
	}

	// 获取仓库路径用于锁定
	repoPath, err := hi.locator.GetRepoPath(repo)
	if err != nil {
		return fmt.Errorf("failed to get repo path: %w", err)
	}

	// 使用分布式锁避免重复执行
	lockName := fmt.Sprintf("housekeeping-check-expired-%s", repoPath)
	_, err = hi.lockManager.AcquireLock(ctx, lockName)
	if err != nil {
		if err == archive.ErrLockAlreadyHeld {
			log.Printf("Housekeeping check expired refs for repository %s is already running", repoPath)
			return nil // 不是错误，只是跳过
		}
		return fmt.Errorf("failed to acquire housekeeping lock: %w", err)
	}
	defer func() {
		if err := hi.lockManager.ReleaseLock(lockName); err != nil {
			log.Printf("Failed to release housekeeping lock %s: %v", lockName, err)
		}
	}()

	log.Printf("Processing archive refs for repository in housekeeping: %s", repoPath)

	localRepo := localrepo.New(hi.gitCmdFactory, nil, repo, hi.cfg)

	// 处理keep-around引用
	if err := hi.processKeepAroundRefs(ctx, repo, localRepo, repoPath); err != nil {
		log.Printf("Failed to process keep-around refs: %v", err)
	}

	// 处理merge-requests引用
	if err := hi.processMergeRequestRefs(ctx, repo, localRepo, repoPath); err != nil {
		log.Printf("Failed to process merge-requests refs: %v", err)
	}

	return nil
}

// processKeepAroundRefs 处理keep-around引用
func (hi *HousekeepingIntegration) processKeepAroundRefs(ctx context.Context, repo repository.GitRepo, localRepo *localrepo.Repo, repoPath string) error {
	// 查询当前主仓的所有keep-around引用
	refs, err := hi.gitOperations.ListRefs(ctx, localRepo, "refs/keep-around/")
	if err != nil {
		return fmt.Errorf("failed to list keep-around refs: %w", err)
	}

	// 读取现有的waiting目录下的keep-around引用
	existingEntries, err := hi.storageManager.ReadMetadata(repoPath, "keep-around", archive.StatusWaiting)
	if err != nil {
		return fmt.Errorf("failed to read existing keep-around waiting metadata: %w", err)
	}

	// 创建现有引用的map，用于快速查找
	existingRefs := make(map[string]archive.MetadataEntry)
	var expiredEntries []archive.MetadataEntry
	now := time.Now()
	retentionPeriod := time.Duration(hi.config.KeepAroundRetentionDays) * 24 * time.Hour

	for _, entry := range existingEntries {
		existingRefs[entry.SourceRefName] = entry

		// 检查是否超期（基于waiting元数据的创建时间）
		if now.Sub(entry.CreateAt) > retentionPeriod {
			expiredEntries = append(expiredEntries, entry)
		}
	}

	// 找出那些没有存在waiting目录下的引用，为它们创建新的waiting条目
	var newEntries []archive.MetadataEntry

	for refName, commitID := range refs {
		if _, exists := existingRefs[refName]; !exists {
			// 新发现的keep-around引用，创建waiting条目（从现在开始计时）
			entry := archive.MetadataEntry{
				Action:         archive.ActionArchive,
				SourceRefName:  refName,
				SourceCommitID: commitID,
				TargetRefName:  archive.GenerateArchivedRefName(refName, commitID),
				CreatorID:      0, // System-generated
				CreatorName:    "housekeeping",
				CreateAt:       now, // 使用当前时间作为创建时间，从现在开始计时
				UpdateAt:       now,
				Status:         archive.StatusWaiting,
				Reason:         "Keep-around ref scheduled for archival (housekeeping)",
			}
			newEntries = append(newEntries, entry)
		}
	}

	// 将新引用写入waiting目录
	if len(newEntries) > 0 {
		taskID := fmt.Sprintf("housekeeping-keep-around-new-%d", now.Unix())
		if err := hi.storageManager.WriteMetadata(repoPath, newEntries, archive.StatusWaiting, taskID); err != nil {
			return fmt.Errorf("failed to write new keep-around refs to waiting: %w", err)
		}
		log.Printf("Added %d new keep-around refs to waiting directory", len(newEntries))
	}

	// 处理过期的引用（基于waiting元数据的创建时间）
	if len(expiredEntries) > 0 {
		if err := hi.submitExpiredRefs(ctx, repo, repoPath, expiredEntries, "keep-around"); err != nil {
			log.Printf("Failed to submit expired keep-around refs: %v", err)
		} else {
			log.Printf("Submitted %d expired keep-around refs for processing (based on waiting metadata creation time)", len(expiredEntries))
		}
	}

	return nil
}

// processMergeRequestRefs 处理merge-requests引用，支持批量和增量获取
func (hi *HousekeepingIntegration) processMergeRequestRefs(ctx context.Context, repo repository.GitRepo, localRepo *localrepo.Repo, repoPath string) error {
	// 查询当前主仓库中所有的merge-requests引用
	refs, err := hi.gitOperations.ListRefs(ctx, localRepo, "refs/merge-requests/")
	if err != nil {
		return fmt.Errorf("failed to list merge-requests refs: %w", err)
	}

	// 读取现有的waiting目录下的merge-requests引用
	existingEntries, err := hi.storageManager.ReadMetadata(repoPath, "merge-requests", archive.StatusWaiting)
	if err != nil {
		return fmt.Errorf("failed to read existing merge-requests waiting metadata: %w", err)
	}

	// 创建现有引用的map，用于快速查找
	existingRefs := make(map[string]archive.MetadataEntry)
	var expiredEntries []archive.MetadataEntry
	now := time.Now()
	retentionPeriod := time.Duration(hi.config.MergeRequestRetentionDays) * 24 * time.Hour

	for _, entry := range existingEntries {
		existingRefs[entry.SourceRefName] = entry

		// 检查是否超期（基于waiting元数据的创建时间）
		if now.Sub(entry.CreateAt) > retentionPeriod {
			expiredEntries = append(expiredEntries, entry)
		}
	}

	// 获取上次处理的时间戳
	lastProcessedTime, err := hi.getLastMRProcessedTime(repoPath)
	if err != nil {
		log.Printf("Failed to get last MR processed time, will process all: %v", err)
		lastProcessedTime = time.Time{} // 设为零值，表示首次处理
	}

	// 提取所有候选的MR IIDs（没有在waiting目录的引用）
	var candidateIIDs []string
	candidateRefsMap := make(map[string]string) // iid -> refName

	for refName, commitID := range refs {
		if _, exists := existingRefs[refName]; !exists {
			// 提取MR IID：refs/merge-requests/{iid}/head
			parts := strings.Split(refName, "/")
			if len(parts) >= 3 {
				iid := parts[2]
				candidateIIDs = append(candidateIIDs, iid)
				candidateRefsMap[iid] = refName
				_ = commitID // 使用commitID防止unused variable警告
			}
		}
	}

	// 批量查询MR状态
	var newEntries []archive.MetadataEntry
	if len(candidateIIDs) > 0 {
		mergedMRs, latestMergedTime, err := hi.batchCheckMergedMRs(ctx, candidateIIDs, lastProcessedTime)
		if err != nil {
			log.Printf("Failed to batch check merged MRs: %v", err)
		} else {
			// 处理已合并的MR，写入waiting目录
			for _, mr := range mergedMRs {
				if refName, exists := candidateRefsMap[mr.IID]; exists {
					if commitID, refExists := refs[refName]; refExists {
						entry := archive.MetadataEntry{
							Action:         archive.ActionArchive,
							SourceRefName:  refName,
							SourceCommitID: commitID,
							TargetRefName:  archive.GenerateArchivedRefName(refName, commitID),
							CreatorID:      0, // System-generated
							CreatorName:    "housekeeping",
							CreateAt:       now, // 使用当前时间作为waiting条目的创建时间
							UpdateAt:       now,
							Status:         archive.StatusWaiting,
							Reason:         fmt.Sprintf("Merged MR (IID: %s, merged at: %s) scheduled for archival (housekeeping)", mr.IID, mr.MergedAt.Format(time.RFC3339)),
						}
						newEntries = append(newEntries, entry)
					}
				}
			}

			// 更新最后处理时间
			if !latestMergedTime.IsZero() {
				if err := hi.saveLastMRProcessedTime(repoPath, latestMergedTime); err != nil {
					log.Printf("Failed to save last MR processed time: %v", err)
				}
			}
		}
	}

	// 将新引用写入waiting目录
	if len(newEntries) > 0 {
		taskID := fmt.Sprintf("housekeeping-merge-requests-new-%d", now.Unix())
		if err := hi.storageManager.WriteMetadata(repoPath, newEntries, archive.StatusWaiting, taskID); err != nil {
			return fmt.Errorf("failed to write new merge-requests refs to waiting: %w", err)
		}
		log.Printf("Added %d new merged merge-requests refs to waiting directory", len(newEntries))
	}

	// 处理过期的引用（基于waiting元数据的创建时间）
	if len(expiredEntries) > 0 {
		if err := hi.submitExpiredRefs(ctx, repo, repoPath, expiredEntries, "merge-requests"); err != nil {
			log.Printf("Failed to submit expired merge-requests refs: %v", err)
		} else {
			log.Printf("Submitted %d expired merge-requests refs for processing (based on waiting metadata creation time)", len(expiredEntries))
		}
	}

	return nil
}

// MergedMRInfo 合并的MR信息
type MergedMRInfo struct {
	IID      string    `json:"iid"`
	MergedAt time.Time `json:"merged_at"`
}

// batchCheckMergedMRs 批量检查MR是否已经合并，支持增量获取
func (hi *HousekeepingIntegration) batchCheckMergedMRs(ctx context.Context, iids []string, lastProcessedTime time.Time) ([]MergedMRInfo, time.Time, error) {
	if len(iids) == 0 {
		return nil, time.Time{}, nil
	}

	if hi.config.APIEndpoint == "" || hi.config.APIToken == "" {
		log.Printf("API endpoint or token not configured, cannot check MR status")
		return nil, time.Time{}, fmt.Errorf("API not configured")
	}

	var mergedMRs []MergedMRInfo
	var latestMergedTime time.Time

	// 如果是首次处理（lastProcessedTime为零值），使用merged_before来获取所有已合并的MR
	if lastProcessedTime.IsZero() {
		log.Printf("First time processing MRs, will check all merged MRs")
		// 使用当前时间作为merged_before，获取所有已合并的MR
		mergedMRs, latestMergedTime = hi.getMergedMRsBefore(ctx, iids, time.Now())
	} else {
		// 增量处理：使用merged_after来获取自上次处理以来新合并的MR
		log.Printf("Incremental processing MRs since %s", lastProcessedTime.Format(time.RFC3339))
		mergedMRs, latestMergedTime = hi.getMergedMRsAfter(ctx, iids, lastProcessedTime)
	}

	return mergedMRs, latestMergedTime, nil
}

// getMergedMRsBefore 获取指定时间之前合并的MR
func (hi *HousekeepingIntegration) getMergedMRsBefore(ctx context.Context, iids []string, beforeTime time.Time) ([]MergedMRInfo, time.Time) {
	var mergedMRs []MergedMRInfo
	var latestMergedTime time.Time

	// 这里应该实现实际的GitLab API调用
	// GET /api/v4/projects/{project_id}/merge_requests?state=merged&merged_before={beforeTime}
	// 然后过滤出在iids列表中的MR

	// 占位符实现：模拟API调用
	for _, iid := range iids {
		// 模拟API响应：假设IID为偶数的MR已合并
		if iidInt, err := strconv.Atoi(iid); err == nil && iidInt%2 == 0 {
			// 模拟合并时间：使用当前时间减去一个随机的天数
			mergedAt := beforeTime.Add(-time.Duration(iidInt) * time.Hour)
			mergedMRs = append(mergedMRs, MergedMRInfo{
				IID:      iid,
				MergedAt: mergedAt,
			})

			// 更新最新合并时间
			if mergedAt.After(latestMergedTime) {
				latestMergedTime = mergedAt
			}
		}
	}

	log.Printf("Found %d merged MRs before %s", len(mergedMRs), beforeTime.Format(time.RFC3339))
	return mergedMRs, latestMergedTime
}

// getMergedMRsAfter 获取指定时间之后合并的MR
func (hi *HousekeepingIntegration) getMergedMRsAfter(ctx context.Context, iids []string, afterTime time.Time) ([]MergedMRInfo, time.Time) {
	var mergedMRs []MergedMRInfo
	var latestMergedTime time.Time

	// 这里应该实现实际的GitLab API调用
	// GET /api/v4/projects/{project_id}/merge_requests?state=merged&merged_after={afterTime}
	// 然后过滤出在iids列表中的MR

	// 占位符实现：模拟增量API调用
	for _, iid := range iids {
		// 模拟API响应：假设IID为偶数且大于某个值的MR在指定时间后合并
		if iidInt, err := strconv.Atoi(iid); err == nil && iidInt%2 == 0 && iidInt > 10 {
			// 模拟合并时间：使用指定时间后的随机时间
			mergedAt := afterTime.Add(time.Duration(iidInt%24) * time.Hour)
			if mergedAt.Before(time.Now()) { // 只包含已经发生的合并
				mergedMRs = append(mergedMRs, MergedMRInfo{
					IID:      iid,
					MergedAt: mergedAt,
				})

				// 更新最新合并时间
				if mergedAt.After(latestMergedTime) {
					latestMergedTime = mergedAt
				}
			}
		}
	}

	log.Printf("Found %d merged MRs after %s", len(mergedMRs), afterTime.Format(time.RFC3339))
	return mergedMRs, latestMergedTime
}

// getLastMRProcessedTime 获取上次处理MR的时间戳
func (hi *HousekeepingIntegration) getLastMRProcessedTime(repoPath string) (time.Time, error) {
	timestampFile := filepath.Join(repoPath, "info", "archive", "mr_last_processed_time")

	data, err := ioutil.ReadFile(timestampFile)
	if err != nil {
		if os.IsNotExist(err) {
			return time.Time{}, nil // 文件不存在，返回零值
		}
		return time.Time{}, err
	}

	return time.Parse(time.RFC3339, strings.TrimSpace(string(data)))
}

// saveLastMRProcessedTime 保存最后处理MR的时间戳
func (hi *HousekeepingIntegration) saveLastMRProcessedTime(repoPath string, timestamp time.Time) error {
	timestampFile := filepath.Join(repoPath, "info", "archive", "mr_last_processed_time")

	// 确保目录存在
	if err := os.MkdirAll(filepath.Dir(timestampFile), 0755); err != nil {
		return err
	}

	return ioutil.WriteFile(timestampFile, []byte(timestamp.Format(time.RFC3339)), 0644)
}

// checkMergedMRs 检查MR是否已经合并
func (hi *HousekeepingIntegration) checkMergedMRs(ctx context.Context, iids []string) map[string]bool {
	mergedIIDs := make(map[string]bool)

	if len(iids) == 0 {
		return mergedIIDs
	}

	// 调用API接口查询MR状态
	if hi.config.APIEndpoint == "" || hi.config.APIToken == "" {
		log.Printf("API endpoint or token not configured, cannot check MR status")
		return mergedIIDs
	}

	// 这里应该实现实际的GitLab API调用
	// 示例实现：批量查询MR状态
	for _, iid := range iids {
		// 实际的API调用逻辑
		// GET /api/v4/projects/{project_id}/merge_requests/{merge_request_iid}
		// 检查state字段是否为"merged"

		// 占位符：假设IID为偶数的MR已合并（实际应该调用API）
		if iidInt, err := strconv.Atoi(iid); err == nil && iidInt%2 == 0 {
			mergedIIDs[iid] = true
		}

		log.Printf("Checked MR IID %s: merged=%v", iid, mergedIIDs[iid])
	}

	return mergedIIDs
}

// submitExpiredRefs 将超期引用发送到kafka处理
func (hi *HousekeepingIntegration) submitExpiredRefs(ctx context.Context, repo repository.GitRepo, repoPath string, entries []archive.MetadataEntry, refType string) error {
	// 按action分组处理（虽然这里都是archive action）
	entriesByAction := make(map[archive.OperationAction][]archive.MetadataEntry)
	for _, entry := range entries {
		entriesByAction[entry.Action] = append(entriesByAction[entry.Action], entry)
	}

	// 为每个action创建单独的任务
	for action, actionEntries := range entriesByAction {
		taskID := fmt.Sprintf("housekeeping-%s-expired-%s-%d", refType, action, time.Now().Unix())

		// 构建元数据文件名
		metadataFileName := fmt.Sprintf("refs-list-%d-%s-%s.json", time.Now().Unix(), taskID, action)

		// 发送kafka消息
		if hi.kafkaProducer != nil && hi.kafkaProducer.IsEnabled() {
			if err := hi.kafkaProducer.SendTaskMessage(ctx, taskID, repoPath, repo.GetStorageName(), metadataFileName); err != nil {
				log.Printf("Failed to send expired %s refs to Kafka: %v", refType, err)
				// Don't return error here - metadata is already written
			} else {
				log.Printf("Successfully sent expired %s refs task %s to Kafka", refType, taskID)
			}
		}
	}

	return nil
}

// isRefExpired 检查引用是否过期，根据不同类型采用不同的判断方法
func (hi *HousekeepingIntegration) isRefExpired(ctx context.Context, localRepo *localrepo.Repo, refName, commitID string, refType string, retentionPeriod time.Duration, now time.Time) bool {
	switch {
	case strings.HasPrefix(refName, "refs/keep-around/"):
		// keep-around引用：以创建时间判断
		return hi.isKeepAroundRefExpired(ctx, localRepo, refName, commitID, retentionPeriod, now)

	case strings.HasPrefix(refName, "refs/merge-requests/"):
		// merge-requests引用：以MR的合入时间判断
		return hi.isMergeRequestRefExpired(ctx, localRepo, refName, commitID, retentionPeriod, now)

	case strings.HasPrefix(refName, "refs/heads/"):
		// 分支引用：以分支的更新时间或最新Commit的提交时间判断
		return hi.isBranchRefExpired(ctx, localRepo, refName, commitID, retentionPeriod, now)

	case strings.HasPrefix(refName, "refs/tags/"):
		// 标签引用：以创建时间为准
		return hi.isTagRefExpired(ctx, localRepo, refName, commitID, retentionPeriod, now)

	default:
		// 其他类型引用，使用默认逻辑
		return hi.isDefaultRefExpired(ctx, localRepo, refName, commitID, retentionPeriod, now)
	}
}

// isKeepAroundRefExpired 检查keep-around引用是否过期（基于创建时间）
func (hi *HousekeepingIntegration) isKeepAroundRefExpired(ctx context.Context, localRepo *localrepo.Repo, refName, commitID string, retentionPeriod time.Duration, now time.Time) bool {
	// 获取commit的创建时间
	commitTime, err := hi.getCommitTime(ctx, localRepo, commitID)
	if err != nil {
		log.Printf("Failed to get commit time for keep-around ref %s: %v", refName, err)
		return false
	}

	return now.Sub(commitTime) > retentionPeriod
}

// isMergeRequestRefExpired 检查merge-request引用是否过期（基于MR合入时间）
func (hi *HousekeepingIntegration) isMergeRequestRefExpired(ctx context.Context, localRepo *localrepo.Repo, refName, commitID string, retentionPeriod time.Duration, now time.Time) bool {
	// 从引用名提取MR IID
	parts := strings.Split(refName, "/")
	if len(parts) < 3 {
		return false
	}
	iid := parts[2]

	// 调用API检查MR的合入时间
	mergeTime, err := hi.getMRMergeTime(ctx, iid)
	if err != nil {
		log.Printf("Failed to get MR merge time for ref %s (IID: %s): %v", refName, iid, err)
		return false
	}

	// 如果MR未合入，不过期
	if mergeTime.IsZero() {
		return false
	}

	return now.Sub(mergeTime) > retentionPeriod
}

// isBranchRefExpired 检查分支引用是否过期（基于分支更新时间或最新Commit提交时间）
func (hi *HousekeepingIntegration) isBranchRefExpired(ctx context.Context, localRepo *localrepo.Repo, refName, commitID string, retentionPeriod time.Duration, now time.Time) bool {
	// 获取分支最新commit的提交时间
	commitTime, err := hi.getCommitTime(ctx, localRepo, commitID)
	if err != nil {
		log.Printf("Failed to get commit time for branch ref %s: %v", refName, err)
		return false
	}

	return now.Sub(commitTime) > retentionPeriod
}

// isTagRefExpired 检查标签引用是否过期（基于标签创建时间）
func (hi *HousekeepingIntegration) isTagRefExpired(ctx context.Context, localRepo *localrepo.Repo, refName, commitID string, retentionPeriod time.Duration, now time.Time) bool {
	// 获取标签的创建时间
	tagTime, err := hi.getTagTime(ctx, localRepo, refName)
	if err != nil {
		log.Printf("Failed to get tag time for ref %s: %v", refName, err)
		// 如果无法获取标签时间，使用commit时间
		commitTime, err := hi.getCommitTime(ctx, localRepo, commitID)
		if err != nil {
			return false
		}
		return now.Sub(commitTime) > retentionPeriod
	}

	return now.Sub(tagTime) > retentionPeriod
}

// isDefaultRefExpired 默认的引用过期检查（基于commit时间）
func (hi *HousekeepingIntegration) isDefaultRefExpired(ctx context.Context, localRepo *localrepo.Repo, refName, commitID string, retentionPeriod time.Duration, now time.Time) bool {
	commitTime, err := hi.getCommitTime(ctx, localRepo, commitID)
	if err != nil {
		log.Printf("Failed to get commit time for ref %s: %v", refName, err)
		return false
	}

	return now.Sub(commitTime) > retentionPeriod
}

// getCommitTime 获取commit的创建时间
func (hi *HousekeepingIntegration) getCommitTime(ctx context.Context, localRepo *localrepo.Repo, commitID string) (time.Time, error) {
	cmd, err := localRepo.Exec(ctx, git.SubCmd{
		Name:  "log",
		Flags: []git.Option{git.Flag{Name: "--format=%ct"}, git.Flag{Name: "-1"}},
		Args:  []string{commitID},
	})
	if err != nil {
		return time.Time{}, err
	}

	output, err := cmd.Output()
	if err != nil {
		return time.Time{}, err
	}

	timestampStr := strings.TrimSpace(string(output))
	if timestampStr == "" {
		return time.Time{}, fmt.Errorf("empty timestamp")
	}

	// 解析Unix时间戳
	var timestamp int64
	if _, err := fmt.Sscanf(timestampStr, "%d", &timestamp); err != nil {
		return time.Time{}, fmt.Errorf("failed to parse timestamp: %w", err)
	}

	return time.Unix(timestamp, 0), nil
}

// getTagTime 获取标签的创建时间
func (hi *HousekeepingIntegration) getTagTime(ctx context.Context, localRepo *localrepo.Repo, refName string) (time.Time, error) {
	// 尝试获取标签对象的创建时间
	cmd, err := localRepo.Exec(ctx, git.SubCmd{
		Name:  "cat-file",
		Flags: []git.Option{git.Flag{Name: "-t"}},
		Args:  []string{refName},
	})
	if err != nil {
		return time.Time{}, err
	}

	output, err := cmd.Output()
	if err != nil {
		return time.Time{}, err
	}

	objectType := strings.TrimSpace(string(output))

	if objectType == "tag" {
		// 对于annotated tag，获取tag对象的创建时间
		cmd, err := localRepo.Exec(ctx, git.SubCmd{
			Name:  "cat-file",
			Flags: []git.Option{git.Flag{Name: "-p"}},
			Args:  []string{refName},
		})
		if err != nil {
			return time.Time{}, err
		}

		output, err := cmd.Output()
		if err != nil {
			return time.Time{}, err
		}

		// 解析tag对象中的tagger时间
		lines := strings.Split(string(output), "\n")
		for _, line := range lines {
			if strings.HasPrefix(line, "tagger ") {
				parts := strings.Fields(line)
				if len(parts) >= 3 {
					timestampStr := parts[len(parts)-2]
					var timestamp int64
					if _, err := fmt.Sscanf(timestampStr, "%d", &timestamp); err == nil {
						return time.Unix(timestamp, 0), nil
					}
				}
			}
		}
	}

	// 对于lightweight tag或解析失败，返回错误让调用者使用commit时间
	return time.Time{}, fmt.Errorf("could not determine tag creation time")
}

// getMRMergeTime 获取MR的合入时间
func (hi *HousekeepingIntegration) getMRMergeTime(ctx context.Context, iid string) (time.Time, error) {
	// 这里应该调用GitLab API获取MR的合入时间
	// TODO: 实现实际的API调用

	if hi.config.APIEndpoint == "" || hi.config.APIToken == "" {
		return time.Time{}, fmt.Errorf("API endpoint or token not configured")
	}

	// 占位符实现：假设偶数IID的MR已合入，并返回当前时间减去保留期作为合入时间
	if iidInt, err := strconv.Atoi(iid); err == nil && iidInt%2 == 0 {
		// 模拟合入时间为30天前
		return time.Now().Add(-30 * 24 * time.Hour), nil
	}

	// 未合入的MR返回零时间
	return time.Time{}, nil
}
